package main.Concurrent.Iteration;

import java.io.ObjectInputStream.GetField;

import com.googlecode.actorom.Actor;
import com.googlecode.actorom.KillActorException;
import com.googlecode.actorom.Topology;
import com.googlecode.actorom.local.LocalTopology;
import com.googlecode.actorom.support.ThreadingPolicies;

import main.Concurrent.Iteration.IterationOperation;
import main.Concurrent.Topology.TopologyManager;
import main.initiate.Configuration;

public class IterationHelper {
    private IterationHelper() { }
    
    /**
     * 
     * @param id Identifier, needs to be unique across topologies
     * @param source The source to iterate
     * @param op The operation to run
     * @param length
     * @return The aggregate result of the operation (maybe just a throwaway value)
     * @throws InterruptedException
     */
    public static <E, R, A> A runIteration(String id, Iterable<E> source, IterationOperation<E, R, A> op, A initialAggregate, int length) {
        IterationHandler<E, R, A> handler = new IterationHandler<E, R, A>(source, op, length);
        TopologyManager m = TopologyManager.getSingleton();
        Topology t = m.getTopology();
        Actor actor = t.spawnAndGetActor(m.getRandomID(id), handler);
        actor.send(new IterationStartMessage<A>(initialAggregate));
        
        A res;
        try {
            res = handler.latch();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return res;
    }
    
    /**
     * 
     * @param id Identifier, needs to be unique across topologies
     * @param source The source to iterate
     * @param op The operation to run
     * @return The aggregate result of the operation
     * @throws InterruptedException
     */
    public static <E, R, A> A runIteration(String id, Iterable<E> source, IterationOperation<E, R, A> op, A initialAggregate) {
        IterationHandler<E, R, A> handler = new IterationHandler<E, R, A>(source, op);
        TopologyManager m = TopologyManager.getSingleton();
        Topology t = m.getTopology();
        Actor actor = t.spawnAndGetActor(m.getRandomID(id), handler);
        actor.send(new IterationStartMessage<A>(initialAggregate));
        
        A res;
        try {
            res = handler.latch();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return res;
    }
}
